﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;


namespace IronWinter
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class NetworkGameAlpha : Microsoft.Xna.Framework.Game
    {
        #region Constants
        public const int BAR_SIZE = 200;
        public const int MAP_SIZE = 200;
        public const int SELECTION_SIZE = 475;

        public const int BUTTON_SPACING = 50;

        public const int ACTIVELIMIT = 6;

        public const int MAX_POINTS = 1000;

        public enum Menu { TitleScreen, MainMenu, CustomMenu, networkMenu, SettingsMenu, InGame, PauseMenu, EditMenu, EndGame }

        #endregion

        #region Variables
        SpriteFont font;
        Camera camera;
        Cursor mouseCursor;
        MouseState mouseState, mouseStatePrev;
        KeyboardState keyState, keyStatePrev;
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        public static Texture2D genericTexture;
        Texture2D cursorTexture, titleScreen, screenBG;

        List<AvailableNetworkSession> avalableNetworkSessions;

        //Equipment Library
        Player currentPlayer;
        int pointsFree;
        public static List<Player> players;

        List<Unit> currentSelection;
        Building currentBuildingSelection;
        Boolean invalidUnits;

        Rectangle selectionBox;
        Point selectionCorner;

        List<Unit>[] ctrlGroups;

        Menu menuState;
        List<MenuButton> mainMenuButtons, buildingMenuButtons, abilityMenuButtons, pauseMenuButtons, customMenuButtons, customUnitButtons, editMenuButtons, networkMenuButtons, joinNetworkButtons;

        MenuButton currentButton, currentUnitButton, currentUpButton, editUnitButton, editBackButton;

        Texture2D buttonTexture;

        public static Texture2D lightUnit, mediumUnit, heavyUnit, HQ, building, objective;

        String EndGameMessage;
        Map currentMap;
        // TextureLibrary
        AbilityLibrary abilityLibrary;

        NetworkSession networkSession;
        AvailableNetworkSessionCollection availableSessions;
        int selectedSessionIndex;
        PacketReader packetReader = new PacketReader();
         PacketWriter packetWriter = new PacketWriter();


        #endregion

        #region Initialization

        public NetworkGameAlpha()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.PreferredBackBufferWidth = Properties.Settings.Default.ResX;
            graphics.PreferredBackBufferHeight = Properties.Settings.Default.ResY;
            graphics.IsFullScreen = Properties.Settings.Default.Fullscreen;

            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// 
        /// </summary>
        protected override void Initialize()
        {
            invalidUnits = false;
            currentSelection = new List<Unit>();

            // Initalize Alpha game
            players = new List<Player>();
            players.Add(new Player());
            players.Add(new Player());

            int k = 1;
            foreach (Player i in players)
            {
                i.Initialize(k);
                k++;
            }
            currentPlayer = players[0];

            ctrlGroups = new List<Unit>[10];
            for (int i = 0; i < 10; i++)
                ctrlGroups[i] = new List<Unit>();

            mainMenuButtons = new List<MenuButton>();

            joinNetworkButtons = new List<MenuButton>();

            networkMenuButtons = new List<MenuButton>();

            buildingMenuButtons = new List<MenuButton>();

            abilityMenuButtons = new List<MenuButton>();

            customMenuButtons = new List<MenuButton>();

            customUnitButtons = new List<MenuButton>();

            pauseMenuButtons = new List<MenuButton>();

            editMenuButtons = new List<MenuButton>();

            menuState = Menu.MainMenu;
            abilityLibrary = new AbilityLibrary();


            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {

            lightUnit = Content.Load<Texture2D>(@"textures\Light");
            mediumUnit = Content.Load<Texture2D>(@"textures\Medium");
            heavyUnit = Content.Load<Texture2D>(@"textures\Heavy");
            HQ = Content.Load<Texture2D>(@"textures\HQ");
            building = Content.Load<Texture2D>(@"textures\Building");
            objective = Content.Load<Texture2D>(@"textures\Objective");

            camera = new Camera(graphics.GraphicsDevice.Viewport);

            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            titleScreen = Content.Load<Texture2D>(@"textures\TitleScreen");
            screenBG = Content.Load<Texture2D>(@"textures\ScreenBG");
            cursorTexture = Content.Load<Texture2D>(@"textures\mouse-cursor-icon");


            //Temp, obviously
            for (int i = 0; i < 4; i++)
            {
                Ability.AbilityList.Add(new Ability("Temp Ability"));
            }

            //Load ability and equipment textures
            for (int i = 0; i < Ability.AbilityList.Count; i++)
                Ability.AbilityList[i].SetTex(Content.Load<Texture2D>(@"textures\Ability" + i));

            Texture2D[] weapTex = new Texture2D[EquipmentLibrary.WEAPON_COUNT];
            Texture2D[] arTex = new Texture2D[EquipmentLibrary.ARMOR_COUNT];
            Texture2D[] itemTex = new Texture2D[EquipmentLibrary.ITEM_COUNT];

            for (int i = 0; i < weapTex.Length; i++)
                weapTex[i] = Content.Load<Texture2D>(@"textures\Weapon" + i);

            for (int i = 0; i < arTex.Length; i++)
                arTex[i] = Content.Load<Texture2D>(@"textures\Armor" + i);

            for (int i = 0; i < itemTex.Length; i++)
                itemTex[i] = Content.Load<Texture2D>(@"textures\Item" + i);

            EquipmentLibrary.LoadContent(weapTex, arTex, itemTex);

            for (int i = 0; i < Unit.Portraits.Length; i++)
                Unit.Portraits[0] = Content.Load<Texture2D>(@"textures\Portrait" + i);

            loadUnitSet();

            genericTexture = new Texture2D(GraphicsDevice, 1, 1);
            genericTexture.SetData(new Color[] { Color.White });

            mouseCursor = new Cursor(cursorTexture);

            foreach (Player p in players)
            {
                p.units.Add(new Unit(Unit.unitSpecs[0], new Vector2(300 * p.designate, 300 * p.designate), p));
                p.units.Add(new Unit(Unit.unitSpecs[0], new Vector2(300 * p.designate + 100, 300 * p.designate + 100), p));
            }


            font = Content.Load<SpriteFont>(@"Fonts\Miramonte");
            MenuButton.menuFont = font;

            buttonTexture = Content.Load<Texture2D>(@"textures\Button");

            //Create all of the buttons
            Vector2 center = new Vector2(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2);

            //Main menu
            mainMenuButtons.Add(new MenuButton("Play", MenuButton.ButtonAction.Play, new Vector2(center.X - 125, center.Y), buttonTexture));
            mainMenuButtons.Add(new MenuButton("Customize Units", MenuButton.ButtonAction.CustomMenu, new Vector2(center.X - 125, center.Y + 100), buttonTexture));
            mainMenuButtons.Add(new MenuButton("Settings", MenuButton.ButtonAction.SettingsMenu, new Vector2(center.X - 125, center.Y + 200), buttonTexture));
            mainMenuButtons.Add(new MenuButton("Quit", MenuButton.ButtonAction.Quit, new Vector2(center.X - 125, center.Y + 300), buttonTexture));

            //NetworkMenu
            networkMenuButtons.Add(new MenuButton("Host Network Game", MenuButton.ButtonAction.HostGame, new Vector2(center.X - 125, center.Y), buttonTexture));
            networkMenuButtons.Add(new MenuButton("Join Network Game", MenuButton.ButtonAction.FindGame, new Vector2(center.X - 125, center.Y + 100), buttonTexture));
            networkMenuButtons.Add(new MenuButton("Quit", MenuButton.ButtonAction.MainMenu, new Vector2(center.X - 125, 200), buttonTexture));

            //join network Menu

            joinNetworkButtons.Add(new MenuButton("JoinFirstGame", MenuButton.ButtonAction.joingame0, new Vector2(center.X - 125, center.Y), buttonTexture));
            joinNetworkButtons.Add(new MenuButton("JoinFirstGame", MenuButton.ButtonAction.joingame1, new Vector2(center.X - 125, center.Y), buttonTexture));
            joinNetworkButtons.Add(new MenuButton("JoinFirstGame", MenuButton.ButtonAction.joingame2, new Vector2(center.X - 125, center.Y), buttonTexture));
            joinNetworkButtons.Add(new MenuButton("Quit", MenuButton.ButtonAction.MainMenu, new Vector2(center.X - 125, 200), buttonTexture));


            //Customization menu
            int customMenuStart = 200;

            customMenuButtons.Add(new MenuButton("Activate Unit", MenuButton.ButtonAction.ActivateUnit, new Vector2(100, customMenuStart), buttonTexture));
            //customMenuButtons.Add(new MenuButton("Add Unit", MenuButton.ButtonAction.AddUnit, new Vector2(100, customMenuStart + (MenuButton.height + BUTTON_SPACING)), buttonTexture));
            //customMenuButtons.Add(new MenuButton("Duplicate Unit", MenuButton.ButtonAction.DupUnit, new Vector2(100, customMenuStart + (MenuButton.height + BUTTON_SPACING) * 2), buttonTexture));
            customMenuButtons.Add(new MenuButton("Edit Unit", MenuButton.ButtonAction.EditUnit, new Vector2(100, customMenuStart + (MenuButton.height + BUTTON_SPACING)), buttonTexture));
            //customMenuButtons.Add(new MenuButton("Remove Unit", MenuButton.ButtonAction.RemUnit, new Vector2(100, customMenuStart + (MenuButton.height + BUTTON_SPACING) * 4), buttonTexture));
            customMenuButtons.Add(new MenuButton("Back", MenuButton.ButtonAction.MainMenu, new Vector2(100, customMenuStart + (MenuButton.height + BUTTON_SPACING) * 2), buttonTexture));

            //Pause menu
            pauseMenuButtons.Add(new MenuButton("Quit", MenuButton.ButtonAction.MainMenu, new Vector2(center.X - 125, 200), buttonTexture));
            pauseMenuButtons.Add(new MenuButton("Return to Game", MenuButton.ButtonAction.Play, new Vector2(center.X - 125, 300), buttonTexture));

            //Edit menu

            for (int i = 0; i < Ability.AbilityList.Count; i++)
                editMenuButtons.Add(new MenuButton(new Vector2(100 + i * Ability.DISPLAY_SIZE * 1.5f, 150 + MenuButton.cheight), Ability.AbilityList[i].texture,
                    Weapon.types.none, Armor.types.none, Item.types.none, i));

            for (int i = 0; i < EquipmentLibrary.WEAPON_COUNT; i++)
                editMenuButtons.Add(new MenuButton(new Vector2(100 + i * Ability.DISPLAY_SIZE * 1.5f, 150 + MenuButton.cheight + Ability.DISPLAY_SIZE * 1.5f),
                    EquipmentLibrary.getWeapon(i).texture, (Weapon.types)i, Armor.types.none, Item.types.none, -1));

            for (int i = 0; i < EquipmentLibrary.ARMOR_COUNT; i++)
                editMenuButtons.Add(new MenuButton(new Vector2(100 + i * Ability.DISPLAY_SIZE * 1.5f, 150 + MenuButton.cheight + Ability.DISPLAY_SIZE * 1.5f * 2),
                    EquipmentLibrary.getArmor(i).texture, Weapon.types.none, (Armor.types)i, Item.types.none, -1));

            for (int i = 0; i < EquipmentLibrary.ITEM_COUNT; i++)
                editMenuButtons.Add(new MenuButton(new Vector2(100 + i * Ability.DISPLAY_SIZE * 1.5f, 150 + MenuButton.cheight + Ability.DISPLAY_SIZE * 1.5f * 3),
                    EquipmentLibrary.getItem(i).texture, Weapon.types.none, Armor.types.none, (Item.types)i, -1));

            editBackButton = new MenuButton("Back", MenuButton.ButtonAction.CustomMenu, new Vector2(100, GraphicsDevice.Viewport.Bounds.Bottom - MenuButton.height - 100), buttonTexture);


            currentMap = new Map("Level1.iwmap");

            currentMap.initalize(); //for testing

            //End map Test
            currentButton = mainMenuButtons[0];

            mouseCursor = new Cursor(cursorTexture);
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        #endregion

        #region network

        //TODO initalize a hostGame
        private void initilizeHostGame()
        {



        }

        //TODO
        private void joinNetworkGame()
        {


        }

        public void initalizeProfile()
        {

        }

        // TODO


        #endregion


        #region Update
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {

            #region networkPlay

            if (networkSession != null)
            {

            }


            #endregion



            mouseState = Mouse.GetState();
            keyState = Keyboard.GetState();

            switch (menuState)
            {
                case Menu.MainMenu:
                    UpdateMenu(mainMenuButtons);
                    break;
                case Menu.CustomMenu:
                    UpdateMenu(customMenuButtons);
                    break;
                case Menu.EditMenu:
                    UpdateEditMenu();
                    break;
                case Menu.SettingsMenu:
                    //UpdateSettingsMenu();
                    break;
                case Menu.InGame:
                    UpdateGame(gameTime);
                    break;
                case Menu.PauseMenu:
                    UpdateMenu(pauseMenuButtons);
                    break;
                case Menu.EndGame:
                    UpdateMenu(pauseMenuButtons);
                    break;
                default:
                    Console.WriteLine("Error");
                    break;
            }

            mouseStatePrev = mouseState;
            keyStatePrev = keyState;

            base.Update(gameTime);
        }

        protected void UpdateEditMenu()
        {
            bool umouseIn, mouseIn;
            umouseIn = mouseIn = false;
            MenuButton mouseInButton = null;
            foreach (MenuButton mb in editMenuButtons)
            {
                if (mb.bounds.Contains(mouseState.X, mouseState.Y))
                {
                    umouseIn = true;
                    mouseInButton = mb;
                }
            }

            if (editBackButton.bounds.Contains(mouseState.X, mouseState.Y))
            {
                mouseIn = true;
                editBackButton.isSelected = true;
            }
            else
            {
                editBackButton.isSelected = false;
            }

            if (mouseState.LeftButton == ButtonState.Pressed && mouseStatePrev.LeftButton == ButtonState.Released)
            {
                if (umouseIn)
                {
                    foreach (MenuButton mb in editMenuButtons)
                    {
                        if (mb == mouseInButton && mb.isSelected)
                        {
                            if ((int)mb.weapon != -1
                                && (EquipmentLibrary.getWeapon(mb.weapon).value <= pointsFree + EquipmentLibrary.getWeapon(editUnitButton.unit.weapon).value))
                                editUnitButton.unit.weapon = mb.weapon;
                            else if ((int)mb.ar != -1
                                && (EquipmentLibrary.getArmor(mb.ar).value <= pointsFree + EquipmentLibrary.getArmor(editUnitButton.unit.ar).value))
                                editUnitButton.unit.ar = mb.ar;
                            else if ((int)mb.item != -1
                                && (EquipmentLibrary.getItem(mb.item).value <= pointsFree + EquipmentLibrary.getItem(editUnitButton.unit.item).value))
                                editUnitButton.unit.item = mb.item;
                            else if (mb.ability != -1)
                            {
                                if (editUnitButton.unit.abilities.Contains(mb.ability))
                                    editUnitButton.unit.abilities.Remove(mb.ability);
                                else if (editUnitButton.unit.abilities.Count < 3 && Ability.AbilityList[mb.ability].value <= pointsFree)
                                    editUnitButton.unit.abilities.Add(mb.ability);
                            }
                        }

                        mb.isSelected = false;
                    }

                    currentUpButton = mouseInButton;
                    currentUpButton.isSelected = true;
                }
                else if (mouseIn)
                {
                    ActivateButton(editBackButton);
                }

                pointsFree = MAX_POINTS - EquipmentLibrary.getWeapon(editUnitButton.unit.weapon).value - EquipmentLibrary.getArmor(editUnitButton.unit.ar).value - EquipmentLibrary.getItem(editUnitButton.unit.item).value;
                foreach (int i in editUnitButton.unit.abilities)
                    pointsFree -= Ability.AbilityList[i].value;
            }
        }

        protected void UpdateMenu(List<MenuButton> list)
        {
            //Select buttons. Mouse overrides keyboard, can be switched around if people prefer
            if (keyState.IsKeyDown(Keys.Down) && !keyStatePrev.IsKeyDown(Keys.Down))
                currentButton = list[list.IndexOf(currentButton) + 1 == list.Count ? 0 : list.IndexOf(currentButton) + 1];
            else if (keyState.IsKeyDown(Keys.Up) && !keyStatePrev.IsKeyDown(Keys.Up))
                currentButton = list[list.IndexOf(currentButton) == 0 ? list.Count - 1 : list.IndexOf(currentButton) - 1];

            bool mouseIn, cmouseIn;
            mouseIn = cmouseIn = false;

            foreach (MenuButton mb in list)
            {
                mb.isSelected = false;
                if (mb.bounds.Contains(mouseState.X, mouseState.Y))
                {
                    currentButton = mb;
                    mouseIn = true;
                }
            }

            MenuButton mouseInButton = null;
            if (menuState == Menu.CustomMenu)
                foreach (MenuButton mb in customUnitButtons)
                    if (mb.bounds.Contains(mouseState.X, mouseState.Y))
                    {
                        cmouseIn = true;
                        mouseInButton = mb;
                    }

            currentButton.isSelected = true;

            //Check if buttons are pressed to navigate
            if ((keyState.IsKeyDown(Keys.Enter) && !keyStatePrev.IsKeyDown(Keys.Enter)))
            {
                ActivateButton(currentButton);
            }
            else if (mouseState.LeftButton == ButtonState.Pressed && mouseStatePrev.LeftButton == ButtonState.Released)
            {
                if (mouseIn)
                {
                    ActivateButton(currentButton);
                }
                else if (cmouseIn)
                {
                    foreach (MenuButton mb in customUnitButtons)
                        mb.isSelected = false;

                    currentUnitButton = mouseInButton;
                    currentUnitButton.isSelected = true;
                }
            }
        }

        //Select an action to take based on the button. Currently incomplete
        protected void ActivateButton(MenuButton mb)
        {
            switch (mb.action)
            {
                case MenuButton.ButtonAction.MainMenu:
                    if (menuState == Menu.CustomMenu)
                        saveUnitSet();

                    menuState = Menu.MainMenu;
                    break;
                case MenuButton.ButtonAction.CustomMenu:
                    menuState = Menu.CustomMenu;
                    RefreshUnitList();
                    break;
                case MenuButton.ButtonAction.ActivateUnit:
                    if (currentUnitButton != null)
                        currentUnitButton.unit.isActive = !currentUnitButton.unit.isActive;
                    else
                        break;

                    if (currentUnitButton.unit.isActive)
                        currentPlayer.unitSpecs.Add(currentUnitButton.unit);
                    else if (currentPlayer.unitSpecs.Contains(currentUnitButton.unit))
                        currentPlayer.unitSpecs.Remove(currentUnitButton.unit);

                    break;
                case MenuButton.ButtonAction.EditUnit:
                    if (currentUnitButton != null)
                    {
                        editUnitButton = new MenuButton(currentUnitButton.unit, new Vector2(100, 100), genericTexture);
                        menuState = Menu.EditMenu;
                    }
                    break;
                case MenuButton.ButtonAction.AddUnit:
                    Unit.unitSpecs.Add(new UnitSpecs());
                    RefreshUnitList();
                    break;
                case MenuButton.ButtonAction.DupUnit:
                    if (currentUnitButton != null)
                    {
                        Unit.unitSpecs.Add(new UnitSpecs(currentUnitButton.unit));
                        RefreshUnitList();
                    }
                    break;
                case MenuButton.ButtonAction.RemUnit:
                    if (currentUnitButton != null)
                    {
                        Unit.unitSpecs.Remove(currentUnitButton.unit);
                        RefreshUnitList();
                    }
                    break;
                case MenuButton.ButtonAction.Play:
                    int lightCount, medCount, heavyCount;
                    lightCount = medCount = heavyCount = 2;
                    foreach (UnitSpecs us in currentPlayer.unitSpecs)
                    {
                        switch (us.type)
                        {
                            case Unit.UnitType.Light:
                                lightCount--;
                                break;
                            case Unit.UnitType.Medium:
                                medCount--;
                                break;
                            case Unit.UnitType.Heavy:
                                heavyCount--;
                                break;
                        }
                        
                    }
                case MenuButton.ButtonAction.HostGame:
                    // findGame // TODO
                    break;


                case MenuButton.ButtonAction.FindGame:
                    //StartGame // TODO
                    break;

                    currentPlayer.unitSpecs.Sort();

                    if (lightCount == 0 && medCount == 0 && heavyCount == 0)
                    {
                        menuState = Menu.InGame;
                        Rectangle screen = GraphicsDevice.Viewport.Bounds;
                        Rectangle bar = new Rectangle(screen.Left, screen.Bottom - BAR_SIZE, screen.Width, BAR_SIZE);

                        buildingMenuButtons.Add(new MenuButton(currentPlayer.unitSpecs[0].name, MenuButton.ButtonAction.spawnLightI, (new Vector2(screen.Right - 2 * MenuButton.width - 20, bar.Top + 10)), buttonTexture));
                        buildingMenuButtons.Add(new MenuButton(currentPlayer.unitSpecs[2].name, MenuButton.ButtonAction.spawnMedI, (new Vector2(screen.Right - 2 * MenuButton.width - 20, bar.Top + 70)), buttonTexture));
                        buildingMenuButtons.Add(new MenuButton(currentPlayer.unitSpecs[4].name, MenuButton.ButtonAction.spawnHeavyI, (new Vector2(screen.Right - 2 * MenuButton.width - 20, bar.Top + 130)), buttonTexture));
                        buildingMenuButtons.Add(new MenuButton(currentPlayer.unitSpecs[1].name, MenuButton.ButtonAction.spawnLightII, (new Vector2(screen.Right - 10 - MenuButton.width, bar.Top + 10)), buttonTexture));
                        buildingMenuButtons.Add(new MenuButton(currentPlayer.unitSpecs[3].name, MenuButton.ButtonAction.spawnMedII, (new Vector2(screen.Right - 10 - MenuButton.width, bar.Top + 70)), buttonTexture));
                        buildingMenuButtons.Add(new MenuButton(currentPlayer.unitSpecs[5].name, MenuButton.ButtonAction.spawnHeavyII, (new Vector2(screen.Right - 10 - MenuButton.width, bar.Top + 130)), buttonTexture));
                    }
                    else
                        invalidUnits = true;

                    break;
                case MenuButton.ButtonAction.Quit:
                    this.Exit();
                    break;
                case MenuButton.ButtonAction.spawnLightI: // TODO
                    SpawnUnit(currentPlayer.unitSpecs[0], currentPlayer);
                    break;
                case MenuButton.ButtonAction.spawnLightII:
                    SpawnUnit(currentPlayer.unitSpecs[1], currentPlayer);
                    break;
                case MenuButton.ButtonAction.spawnMedI:
                    SpawnUnit(currentPlayer.unitSpecs[2], currentPlayer);
                    break;
                case MenuButton.ButtonAction.spawnMedII:
                    SpawnUnit(currentPlayer.unitSpecs[3], currentPlayer);
                    break;
                case MenuButton.ButtonAction.spawnHeavyI:
                    SpawnUnit(currentPlayer.unitSpecs[4], currentPlayer);
                    break;
                case MenuButton.ButtonAction.spawnHeavyII:
                    SpawnUnit(currentPlayer.unitSpecs[5], currentPlayer);
                    break;
            }
        }

        protected void SpawnUnit(UnitSpecs us, Player p)
        {
            Unit newUnit = (new Unit(us, currentBuildingSelection.spawnUnitAt(), p));
            if (newUnit.value > currentPlayer.requisition)
                return;

            currentPlayer.requisition -= newUnit.value;
            currentPlayer.units.Add(newUnit);
        }

        protected void RefreshUnitList()
        {
            customUnitButtons.Clear();
            for (int i = 0; i < 3; i++)
                for (int u = i * 3; u < i * 3 + 3 && u < Unit.unitSpecs.Count; u++)
                    customUnitButtons.Add(new MenuButton(Unit.unitSpecs[u], new Vector2(120 + MenuButton.width + 260 * i, 200 + (100 + BUTTON_SPACING) * (u % 3)), genericTexture));

            currentUnitButton = null;

            invalidUnits = false;
        }

        protected void UpdateGame(GameTime gameTime)
        {
            //Check for EndGame Conditions. That is. Only 1 Player Controlls buildings
            int livingPlayers = 0;
            Player winningPlayer = null;
            foreach (Player p in players)
            {
                if (p.buildings.Count() > 0)
                {
                    livingPlayers++;
                    winningPlayer = p;
                }
            }
            if (livingPlayers == 0)
            {
                EndGameMessage = "The game is a Draw,";
                menuState = Menu.EndGame;
                return;
            }
            else if (livingPlayers == 1)
            {
                //WinningPlayer Wins // TODO ENDGAME
                EndGameMessage = "Player: " + winningPlayer.designate + " is the Victor.";
                menuState = Menu.EndGame;
                return;
            }




            if (keyState.IsKeyDown(Keys.Escape))
            {
                menuState = Menu.PauseMenu;
                return;
            }


            //Input related stuff

            mouseCursor.Position = camera.ScreenToWorld(new Vector2(mouseState.X, mouseState.Y));

            //Forattack

            // Move the selected unit to the current mouse position when the left button is pressed
            if (mouseState.RightButton == ButtonState.Pressed)
            {
                bool go = false;
                foreach (Player p in players)
                {
                    foreach (Unit u in p.units)
                    {
                        if (u.player.designate != currentPlayer.designate && u.Bounds.Contains((int)mouseCursor.Position.X, (int)mouseCursor.Position.Y))
                        {
                            go = true;
                            foreach (Unit x in currentSelection)
                            {
                                if (keyState.IsKeyDown(Keys.LeftShift))
                                {
                                    x.appendAttack(u);
                                }
                                else
                                {
                                    x.immediateAttack(u);
                                }

                            }
                        }
                    }

                    // building
                    if (go)
                    {
                        break;
                    }
                    foreach (Building b in p.buildings)
                    {
                        if (b.player.designate != currentPlayer.designate && b.hitBox.Contains((int)mouseCursor.Position.X, (int)mouseCursor.Position.Y))
                        {
                            go = true;
                            foreach (Unit x in currentSelection)
                            {
                                if (keyState.IsKeyDown(Keys.LeftShift))
                                {
                                    x.appendAttack(b);
                                }
                                else
                                {
                                    x.immediateAttack(b);
                                }
                            }
                        }
                    }


                    if (!go)
                        if (keyState.IsKeyDown(Keys.LeftShift))
                        {
                            foreach (Unit u in currentSelection)
                                u.appendWaypoint(mouseCursor.Position);
                        }
                        else
                        {
                            foreach (Unit u in currentSelection)
                                u.setWaypoint(mouseCursor.Position);
                        }
                }

            }

            //Move the camera if the mouse is at the edge of the screen
            if (mouseCursor.Position.X - 10 < camera.screenBounds.Left)
                camera.Move(new Vector2(-10, 0));

            if (mouseCursor.Position.X + 10 > camera.screenBounds.Right)
                camera.Move(new Vector2(10, 0));

            if (mouseCursor.Position.Y - 10 < camera.screenBounds.Top)
                camera.Move(new Vector2(0, -10));

            if (mouseCursor.Position.Y + 10 > camera.screenBounds.Bottom)
                camera.Move(new Vector2(0, 10));

            //Select units

            //Start creating a selection if the button has just been pressed
            if (mouseState.LeftButton == ButtonState.Pressed && mouseStatePrev.LeftButton == ButtonState.Released)
            {
                selectionBox = new Rectangle(mouseCursor.X, mouseCursor.Y, 0, 0);
                selectionCorner.X = mouseCursor.X;
                selectionCorner.Y = mouseCursor.Y;
            }

            //While the button is pressed, grow the selection
            if (mouseState.LeftButton == ButtonState.Pressed)
            {
                int rectX, rectY;

                rectX = (mouseCursor.X - selectionCorner.X < 0) ? mouseCursor.X : selectionCorner.X;
                rectY = (mouseCursor.Y - selectionCorner.Y < 0) ? mouseCursor.Y : selectionCorner.Y;
                selectionBox = new Rectangle(rectX, rectY, Math.Abs(mouseCursor.X - selectionCorner.X), Math.Abs(mouseCursor.Y - selectionCorner.Y));
            }



            if (mouseState.LeftButton == ButtonState.Released)
            {
                if (mouseStatePrev.LeftButton == ButtonState.Pressed)
                {
                    if (currentBuildingSelection != null)
                    {
                        bool buildingCall = false;
                        foreach (MenuButton mb in buildingMenuButtons)
                        {
                            mb.isSelected = false;
                            if (mb.bounds.Contains(mouseState.X, mouseState.Y))
                            {
                                currentButton = mb;
                                buildingCall = true;
                                //TODO
                                ActivateButton(mb);
                                break;
                            }
                        }
                        if (!buildingCall)
                        {
                            currentBuildingSelection.isSelected = false;
                            currentBuildingSelection = null;
                        }
                    }
                }

                // Move on to map
                if (mouseState.Y < GraphicsDevice.Viewport.Bounds.Bottom - BAR_SIZE)
                {
                    //If the button was just released, execute the selection
                    if (mouseStatePrev.LeftButton == ButtonState.Pressed)
                    {
                        if (keyState.IsKeyUp(Keys.LeftShift))
                            currentSelection.Clear();
                        foreach (Player p in players)
                        {
                            foreach (Unit u in p.units)
                            {
                                if (u.player != currentPlayer)
                                    continue;

                                if (selectionBox.Intersects(u.Bounds))
                                {
                                    currentSelection.Add(u);
                                    u.isSelected = true;
                                }
                                else
                                {
                                    u.isSelected = false;
                                }
                            }
                            if (currentSelection.Count != 0)
                            {
                                break;
                            }
                            foreach (Building b in p.buildings)
                            {
                                if (b.player != currentPlayer)
                                    continue;

                                if (selectionBox.Intersects(b.hitBox))
                                {
                                    currentBuildingSelection = b;
                                    b.isSelected = true;
                                }

                            }
                        }
                    }
                }
                //Reset the selection box
                selectionBox = new Rectangle(-1, -1, 0, 0);
            }

            //Handle control groups
            if (keyState.IsKeyDown(Keys.D1))
                if (keyState.IsKeyDown(Keys.LeftControl))
                {
                    ctrlGroups[1].Clear();
                    ctrlGroups[1].AddRange(currentSelection);
                }
                else if (ctrlGroups[1].Count != 0)
                {
                    foreach (Unit u in ctrlGroups[1])
                        u.isSelected = true;

                    currentSelection.AddRange(ctrlGroups[1]);
                }

            //Center the camera on the selected unit if Space is pressed
            if (keyState.IsKeyDown(Keys.Space))
                camera.LookAt(currentSelection[0]);

            foreach (Player p in players)
            {
                p.Update(gameTime);
            }
            //currentMap.update();
            currentMap.update();
        }

        #endregion

        #region Draw

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            switch (menuState)
            {
                case Menu.MainMenu:
                    DrawMainMenu();
                    break;
                case Menu.CustomMenu:
                    DrawCustomMenu();
                    break;
                case Menu.EditMenu:
                    DrawEditMenu();
                    break;
                case Menu.InGame:
                    DrawGame();
                    break;
                case Menu.PauseMenu:
                    DrawPauseMenu();
                    break;
                case Menu.EndGame:
                    DrawEndGame();
                    break;
                default:
                    Console.WriteLine("Error");
                    break;
            }

            spriteBatch.Begin();
            spriteBatch.Draw(cursorTexture, new Vector2(Mouse.GetState().X, Mouse.GetState().Y), Color.White); //Cursor
            spriteBatch.End();

            base.Draw(gameTime);
        }

        protected void DrawEndGame()
        {
            spriteBatch.Begin();

            spriteBatch.DrawString(font, EndGameMessage, new Vector2(300, 300), Color.Red);

            spriteBatch.Draw(genericTexture, new Rectangle(GraphicsDevice.Viewport.Width / 2 - 150, GraphicsDevice.Viewport.Height / 2 - 250, 300, 250), Color.Black);

            foreach (MenuButton mb in pauseMenuButtons)
            {
                mb.Draw(spriteBatch);
                break;
            }

            spriteBatch.End();

        }

        protected void DrawEditMenu()
        {
            spriteBatch.Begin();
            spriteBatch.Draw(screenBG, GraphicsDevice.Viewport.Bounds, Color.White);
            foreach (MenuButton mb in editMenuButtons)
            {
                if (editUnitButton.unit.weapon == mb.weapon || editUnitButton.unit.ar == mb.ar || editUnitButton.unit.item == mb.item
                    || editUnitButton.unit.abilities.Contains(mb.ability))
                    spriteBatch.Draw(genericTexture, new Rectangle(mb.bounds.X - 10, mb.bounds.Y - 10, mb.bounds.Width + 20, mb.bounds.Height + 20), Color.Green);

                mb.Draw(spriteBatch);
            }
            editUnitButton.Draw(spriteBatch);

            Rectangle unitBox = new Rectangle(editUnitButton.bounds.X + editUnitButton.bounds.Width + 50, editUnitButton.bounds.Y, 400, editUnitButton.bounds.Height);
            spriteBatch.Draw(genericTexture, unitBox, Color.Gray);

            spriteBatch.DrawString(MenuButton.menuFont, "Points Remaining: " + pointsFree, new Vector2(unitBox.Right - MenuButton.menuFont.MeasureString("Points Remaining: " + pointsFree).X - 10, unitBox.Y + 10), Color.Red);
            Unit test = new Unit(editUnitButton.unit, Vector2.Zero, currentPlayer);

            spriteBatch.DrawString(MenuButton.menuFont, test.name, new Vector2(unitBox.X + 10, unitBox.Y + 10), Color.Red);
            spriteBatch.DrawString(MenuButton.menuFont, "Health : " + test.maxHealth, new Vector2(unitBox.X + 10, unitBox.Y + 30), Color.Red);
            spriteBatch.DrawString(MenuButton.menuFont, "Armor : " + test.armor, new Vector2(unitBox.X + 10, unitBox.Y + 30 + 20), Color.Red);
            spriteBatch.DrawString(MenuButton.menuFont, "Speed : " + test.moveSpeed, new Vector2(unitBox.X + 10, unitBox.Y + 30 + 40), Color.Red);

            spriteBatch.DrawString(MenuButton.menuFont, "Damage : " + test.atkPow, new Vector2(unitBox.X + 10 + 100, unitBox.Y + 30), Color.Red);
            spriteBatch.DrawString(MenuButton.menuFont, "ArPen : " + test.armorPen, new Vector2(unitBox.X + 10 + 100, unitBox.Y + 30 + 20), Color.Red);
            spriteBatch.DrawString(MenuButton.menuFont, "Attack Move? : " + test.moveWhileAttacking, new Vector2(unitBox.X + 10 + 100, unitBox.Y + 30 + 40), Color.Red);

            Rectangle statBox = new Rectangle(editUnitButton.bounds.X + editUnitButton.bounds.Width + 50 + 400 + 10, editUnitButton.bounds.Y, 400, editUnitButton.bounds.Height);
            spriteBatch.Draw(genericTexture, statBox, Color.Gray);

            if (currentUpButton != null)
            {
                Equipment dispEq = null;
                Ability dispAb = null;

                if ((int)currentUpButton.ar != -1)
                    dispEq = EquipmentLibrary.getArmor(currentUpButton.ar);
                else if ((int)currentUpButton.weapon != -1)
                    dispEq = EquipmentLibrary.getWeapon(currentUpButton.weapon);
                else if ((int)currentUpButton.item != -1)
                    dispEq = EquipmentLibrary.getItem(currentUpButton.item);
                else if (currentUpButton.ability != -1)
                    dispAb = Ability.AbilityList[currentUpButton.ability];

                if (dispEq != null)
                {
                    dispEq.Display(spriteBatch, new Rectangle(statBox.X + 10, statBox.Y + 10, Ability.DISPLAY_SIZE, Ability.DISPLAY_SIZE));
                    spriteBatch.DrawString(MenuButton.menuFont, dispEq.name, new Vector2(statBox.X + Ability.DISPLAY_SIZE + 20, statBox.Y + 10), Color.Red);
                    spriteBatch.DrawString(MenuButton.menuFont, "Health : " + dispEq.maxHealth, new Vector2(statBox.X + Ability.DISPLAY_SIZE + 20, statBox.Y + 30), Color.Red);
                    spriteBatch.DrawString(MenuButton.menuFont, "Armor : " + dispEq.armor, new Vector2(statBox.X + Ability.DISPLAY_SIZE + 20, statBox.Y + 30 + 20), Color.Red);
                    spriteBatch.DrawString(MenuButton.menuFont, "Speed : " + dispEq.moveSpeed, new Vector2(statBox.X + Ability.DISPLAY_SIZE + 20, statBox.Y + 30 + 40), Color.Red);
                    spriteBatch.DrawString(MenuButton.menuFont, "Cost : " + dispEq.value, new Vector2(statBox.Right - MenuButton.menuFont.MeasureString("Cost : " + dispEq.value).X - 10, statBox.Y + 10), Color.Red);

                    spriteBatch.DrawString(MenuButton.menuFont, "Damage : " + dispEq.atkPow, new Vector2(statBox.X + Ability.DISPLAY_SIZE + 20 + 100, statBox.Y + 30), Color.Red);
                    spriteBatch.DrawString(MenuButton.menuFont, "ArPen : " + dispEq.armorPen, new Vector2(statBox.X + Ability.DISPLAY_SIZE + 20 + 100, statBox.Y + 30 + 20), Color.Red);
                    spriteBatch.DrawString(MenuButton.menuFont, "Attack Move? : " + dispEq.canMoveWhileAttacking, new Vector2(statBox.X + Ability.DISPLAY_SIZE + 20 + 100, statBox.Y + 30 + 40), Color.Red);
                }
                else if (dispAb != null)
                {
                    dispAb.Display(spriteBatch, new Rectangle(statBox.X + 10, statBox.Y + 10, Ability.DISPLAY_SIZE, Ability.DISPLAY_SIZE));
                    spriteBatch.DrawString(MenuButton.menuFont, dispAb.name, new Vector2(statBox.X + Ability.DISPLAY_SIZE + 20, statBox.Y + 10), Color.Red);
                    spriteBatch.DrawString(MenuButton.menuFont, dispAb.displayText, new Vector2(statBox.X + Ability.DISPLAY_SIZE + 20, statBox.Y + 30), Color.Red);
                    spriteBatch.DrawString(MenuButton.menuFont, "Cost : " + dispAb.value, new Vector2(statBox.Right - MenuButton.menuFont.MeasureString("Cost : " + dispAb.value).X - 10, statBox.Y + 10), Color.Red);

                    spriteBatch.DrawString(MenuButton.menuFont, "Damage : " + dispAb.atkPow, new Vector2(statBox.X + Ability.DISPLAY_SIZE + 20, statBox.Y + 70), Color.Red);
                    spriteBatch.DrawString(MenuButton.menuFont, "ArPen : " + dispAb.armorPen, new Vector2(statBox.X + Ability.DISPLAY_SIZE + 20 + 100, statBox.Y + 70), Color.Red);

                }
            }

            editBackButton.Draw(spriteBatch);

            spriteBatch.End();
        }

        protected void DrawMainMenu()
        {
            spriteBatch.Begin();
            spriteBatch.Draw(titleScreen, GraphicsDevice.Viewport.Bounds, Color.White);
            if (invalidUnits)
                spriteBatch.DrawString(MenuButton.menuFont, "Invalid unit composition", new Vector2(GraphicsDevice.Viewport.Width / 2 - MenuButton.menuFont.MeasureString("Invalid unit composition").X / 2, GraphicsDevice.Viewport.Height / 2 - 50), Color.Red);
            foreach (MenuButton mb in mainMenuButtons)
                mb.Draw(spriteBatch);
            spriteBatch.End();
        }

        protected void DrawNetworkMenu()
        {
             spriteBatch.Begin();
            spriteBatch.Draw(titleScreen, GraphicsDevice.Viewport.Bounds, Color.White);
            foreach (MenuButton mb in networkMenuButtons)
                mb.Draw(spriteBatch);
            spriteBatch.End();
        }

        protected void JoinNetworkMenu() //TODO
        {
            foreach (AvailableNetworkSession availableSession in availableSessions)
            {
                // Create menu entries for each available session.
                MenuEntry menuEntry = new AvailableSessionMenuEntry(availableSession);
                menuEntry.Selected += AvailableSessionMenuEntrySelected;
                MenuEntries.Add(menuEntry);

                // Matchmaking can return up to 25 available sessions at a time, but
                // we don't have room to fit that many on the screen. In a perfect
                // world we should make the menu scroll if there are too many, but it
                // is easier to just not bother displaying more than we have room for.
                if (MenuEntries.Count >= MaxSearchResults)
                    break;
            }
            spriteBatch.Begin();
            spriteBatch.Draw(titleScreen, GraphicsDevice.Viewport.Bounds, Color.White);
            foreach (MenuButton mb in networkMenuButtons)
            {
                if (mb.action == MenuButton.ButtonAction.MainMenu)
                {
                    mb.Draw(spriteBatch);
                }
                mb.Draw(spriteBatch);
            }
            spriteBatch.End();
        }


        protected void DrawCustomMenu()
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();
            spriteBatch.Draw(screenBG, GraphicsDevice.Viewport.Bounds, Color.White);
            //spriteBatch.DrawString(MenuButton.menuFont, "Customization", new Vector2(GraphicsDevice.Viewport.Width / 2 - MenuButton.menuFont.MeasureString("Customization").X / 2, 100), Color.Gray);

            Rectangle specBox = new Rectangle(100, GraphicsDevice.Viewport.Bounds.Bottom - 300, 125, 100);
            spriteBatch.Draw(genericTexture, specBox, Color.Gray);

            int lightCount, medCount, heavyCount;
            lightCount = medCount = heavyCount = 0;
            foreach (UnitSpecs us in currentPlayer.unitSpecs)
            {
                switch (us.type)
                {
                    case Unit.UnitType.Light:
                        lightCount++;
                        break;
                    case Unit.UnitType.Medium:
                        medCount++;
                        break;
                    case Unit.UnitType.Heavy:
                        heavyCount++;
                        break;
                }
            }

            spriteBatch.DrawString(MenuButton.menuFont, "Light : " + lightCount + "/2", new Vector2(specBox.Left + 10, specBox.Top + 10), Color.Red);
            spriteBatch.DrawString(MenuButton.menuFont, "Medium : " + medCount + "/2", new Vector2(specBox.Left + 10, specBox.Top + 35), Color.Red);
            spriteBatch.DrawString(MenuButton.menuFont, "Heavy : " + heavyCount + "/2", new Vector2(specBox.Left + 10, specBox.Top + 60), Color.Red);
            foreach (MenuButton mb in customMenuButtons)
                mb.Draw(spriteBatch);

            foreach (MenuButton mb in customUnitButtons)
                mb.Draw(spriteBatch);

            spriteBatch.End();
        }

        protected void DrawPauseMenu()
        {
            DrawGame();

            spriteBatch.Begin();

            spriteBatch.Draw(genericTexture, new Rectangle(GraphicsDevice.Viewport.Width / 2 - 150, GraphicsDevice.Viewport.Height / 2 - 250, 300, 250), Color.Black);

            foreach (MenuButton mb in pauseMenuButtons)
                mb.Draw(spriteBatch);

            spriteBatch.End();

        }

        protected void DrawGame()
        {
            GraphicsDevice.Clear(Color.SaddleBrown);


            //Draw the game field, translated according to the camera location
            spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, camera.GetViewMatrix());



            foreach (Player p in players)
            {
                p.draw(spriteBatch);
            }

            currentMap.draw(spriteBatch);

            spriteBatch.Draw(genericTexture, selectionBox, new Color(20, 10, 100, 70)); //Selection box

            spriteBatch.End();

            //Draw UI elements at literal screen locations
            spriteBatch.Begin();
            spriteBatch.DrawString(font, "Requisition: " + currentPlayer.requisition, new Vector2(20, 20), Color.DarkTurquoise);

            DrawBottomBar(spriteBatch);
            spriteBatch.End();
        }

        //Draw the bottom bar, with selection details and map
        //A lot of stuff in here is hardcoded that probably shouldn't be, I'll sort it out into constants somewhere later
        protected void DrawBottomBar(SpriteBatch sb)
        {
            Rectangle screen = GraphicsDevice.Viewport.Bounds;
            Rectangle bar = new Rectangle(screen.Left, screen.Bottom - BAR_SIZE, screen.Width, BAR_SIZE);

            sb.Draw(genericTexture, bar, Color.Black);

            //Display selection bg
            sb.Draw(genericTexture, new Rectangle(screen.Left + 20 + MAP_SIZE, bar.Top + 10, SELECTION_SIZE, BAR_SIZE - 20), Color.Gray);

            //Display stats bg
            Rectangle statBox = new Rectangle(screen.Left + 20 + MAP_SIZE + SELECTION_SIZE + 10, bar.Top + 10, SELECTION_SIZE - 295, BAR_SIZE - 20);



            //Display unit stats
            if (currentSelection.Count > 0)
            {
                sb.Draw(genericTexture, statBox, Color.Gray);
                //Display abilities 
                for (int i = 0; i < currentSelection[0].abilities.Count; i++)
                    Ability.AbilityList[currentSelection[0].abilities[i]].Display(sb, new Vector2(screen.Right - (Ability.DISPLAY_SIZE + 10) * 4 + (Ability.DISPLAY_SIZE + 10) * (i + 1), bar.Top + 30));

                //Display equipment
                EquipmentLibrary.getWeapon(currentSelection[0].weapon).Display(sb, new Vector2(screen.Right - (Ability.DISPLAY_SIZE + 10) * 4 + (Ability.DISPLAY_SIZE + 10) * (1), bar.Top + 30 + Ability.DISPLAY_SIZE + 10));
                EquipmentLibrary.getArmor(currentSelection[0].ar).Display(sb, new Vector2(screen.Right - (Ability.DISPLAY_SIZE + 10) * 4 + (Ability.DISPLAY_SIZE + 10) * (2), bar.Top + 30 + Ability.DISPLAY_SIZE + 10));
                EquipmentLibrary.getItem(currentSelection[0].item).Display(sb, new Vector2(screen.Right - (Ability.DISPLAY_SIZE + 10) * 4 + (Ability.DISPLAY_SIZE + 10) * (3), bar.Top + 30 + Ability.DISPLAY_SIZE + 10));

                //Display stats
                spriteBatch.DrawString(MenuButton.menuFont, currentSelection[0].name, new Vector2(statBox.X + 10, statBox.Y + 10), Color.Red);
                spriteBatch.DrawString(MenuButton.menuFont, "Health : " + currentSelection[0].maxHealth, new Vector2(statBox.X + 10, statBox.Y + 30), Color.Red);
                spriteBatch.DrawString(MenuButton.menuFont, "Armor : " + currentSelection[0].armor, new Vector2(statBox.X + 10, statBox.Y + 30 + 20), Color.Red);
                spriteBatch.DrawString(MenuButton.menuFont, "Speed : " + currentSelection[0].moveSpeed, new Vector2(statBox.X + 10, statBox.Y + 30 + 40), Color.Red);

                spriteBatch.DrawString(MenuButton.menuFont, "Damage : " + currentSelection[0].atkPow, new Vector2(statBox.X + 10, statBox.Y + 30 + 60), Color.Red);
                spriteBatch.DrawString(MenuButton.menuFont, "ArPen : " + currentSelection[0].armorPen, new Vector2(statBox.X + 10, statBox.Y + 30 + 80), Color.Red);
                spriteBatch.DrawString(MenuButton.menuFont, "Attack Move? : " + currentSelection[0].moveWhileAttacking, new Vector2(statBox.X + 10, statBox.Y + 30 + 100), Color.Red);

                //Display portrait
                sb.Draw(Unit.Portraits[currentSelection[0].portrait], new Rectangle(screen.Right - (Ability.DISPLAY_SIZE + 10) * 3 - Unit.PORTRAIT_WIDTH - 10, bar.Top + 10, 150, BAR_SIZE - 20), Color.White);

            }
            // TODO
            if (currentBuildingSelection != null)
            {
                foreach (MenuButton b in buildingMenuButtons)
                {
                    b.Draw(sb);
                }
            }


            //Display map
            sb.Draw(genericTexture, new Rectangle(screen.Left + 5, bar.Top + 10, 200, BAR_SIZE - 20), Color.Gray);
        }


        #endregion

        #region Save/Load

        public void saveUnitSet()
        {
            FileStream fs = new FileStream("UnitConfiguration.dat", FileMode.Create);

            BinaryFormatter formatter = new BinaryFormatter();
            try
            {
                formatter.Serialize(fs, Unit.unitSpecs);
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to save unit specs. Reason: " + e.Message);
                throw;
            }
            finally
            {
                fs.Close();
            }
        }

        public void loadUnitSet()
        {
            if (File.Exists("UnitConfiguration.dat"))
            {
                FileStream fs = new FileStream("UnitConfiguration.dat", FileMode.Open);
                try
                {
                    BinaryFormatter formatter = new BinaryFormatter();
                    Unit.unitSpecs = (List<UnitSpecs>)formatter.Deserialize(fs);

                    if (Unit.unitSpecs.Count == 0)
                        ResetUnitSpecs();

                    foreach (UnitSpecs us in Unit.unitSpecs)
                        if (us.isActive)
                            currentPlayer.unitSpecs.Add(us);
                }
                catch (SerializationException e)
                {
                    Console.WriteLine("Failed to load unit specs. Reason: " + e.Message);
                    ResetUnitSpecs();
                }
                finally
                {
                    fs.Close();
                }
            }
            else
            {
                ResetUnitSpecs();
            }
        }

        protected void ResetUnitSpecs()
        {
            Unit.unitSpecs = new List<UnitSpecs>();
            for (int i = 0; i < 3; i++)
            {
                UnitSpecs us = new UnitSpecs();
                us.abilities = new List<int>();
                us.type = Unit.UnitType.Light;
                us.weapon = Weapon.types.revolver;
                us.ar = Armor.types.chitinArmor;
                us.item = Item.types.voloxStimulent;
                us.portraitIndex = 0;
                us.name = "Light Unit " + (i + 1);
                us.isActive = false;
                Unit.unitSpecs.Add(us);
            }

            for (int i = 0; i < 3; i++)
            {
                UnitSpecs us = new UnitSpecs();
                us.abilities = new List<int>();
                us.type = Unit.UnitType.Medium;
                us.weapon = Weapon.types.revolver;
                us.ar = Armor.types.chitinArmor;
                us.item = Item.types.voloxStimulent;
                us.portraitIndex = 0;
                us.name = "Medium Unit " + (i + 1);
                us.isActive = false;
                Unit.unitSpecs.Add(us);
            }

            for (int i = 0; i < 3; i++)
            {
                UnitSpecs us = new UnitSpecs();
                us.abilities = new List<int>();
                us.type = Unit.UnitType.Heavy;
                us.weapon = Weapon.types.revolver;
                us.ar = Armor.types.chitinArmor;
                us.item = Item.types.voloxStimulent;
                us.portraitIndex = 0;
                us.name = "Heavy Unit " + (i + 1);
                us.isActive = false;
                Unit.unitSpecs.Add(us);
            }

        }
        #endregion
    }
}
